package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumInfoIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumInfoIndexRepository albumInfoIndexRepository;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        //  hget key field;
        return (List<AlbumInfoIndex>) redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX+category1Id.toString(),dimension);
    }

    @Override
    public void updateLatelyAlbumRanking() {
        //  将数据从es中放入redis
        //  先获取到所有的一级分类Id；
        Result<List<BaseCategory1>> baseCategory1Result = categoryFeignClient.findAllCategory1();
        Assert.notNull(baseCategory1Result, "一级分类数据集合为空!");
        List<BaseCategory1> baseCategory1List = baseCategory1Result.getData();
        Assert.notNull(baseCategory1List, "一级分类数据为空!");
        //  传递的数据固定：
        String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
        //  动态生成dsl语句.
        baseCategory1List.stream().forEach(baseCategory1 -> {
            for (String ranking : rankingDimensionArray) {
                //  查询数据
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                                    .query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                                    .sort(st -> st.field(f -> f.field(ranking).order(SortOrder.Desc)))
                            ,
                            AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //  获取数据
                List<AlbumInfoIndex> infoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //  将数据存储到缓存.
                //  key=RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId().toString();
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId().toString(),ranking,infoIndexList);
            }
        });
    }

    @Override
    public List<String> completeSuggest(String keyword) {
        //  调用检索方法
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(s -> s.index("suggestinfo")
                            .suggest(st -> st.suggesters("keywordSuggest",
                                            st1 -> st1.prefix(keyword)
                                                    .completion(c -> c.field("keyword").skipDuplicates(true).fuzzy(f -> f.fuzziness("auto")).size(10)))
                                    .suggesters("keywordPinyinSuggest",
                                            st1 -> st1.prefix(keyword)
                                                    .completion(c -> c.field("keywordPinyin").skipDuplicates(true).fuzzy(f -> f.fuzziness("auto")).size(10))
                                    )
                                    .suggesters("keywordSequenceSuggest",
                                            st1 -> st1.prefix(keyword)
                                                    .completion(c -> c.field("keywordSequence").skipDuplicates(true).fuzzy(f -> f.fuzziness("auto")).size(10))
                                    )
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取执行结果：
        //  分别获取到三个key对应的集合数据.然后做合并!
        List<String> stringList = new ArrayList<>();
        stringList.addAll(this.parseResultData(searchResponse, "keywordSuggest"));
        stringList.addAll(this.parseResultData(searchResponse, "keywordPinyinSuggest"));
        stringList.addAll(this.parseResultData(searchResponse, "keywordSequenceSuggest"));
        //  如果：stringList.size()<10; 可以根据关键词检索，将检索的结果添加到集合中；补充到10条数据.
        /*
        GET /albuminfo/_search
        {
          "query": {
            "match": {
              "albumTitle": "三国"
            }
          }
        }
         */
        //  将上述dsl 语句 使用es 客户端生成对应的java 代码
        //  返回数据
        return stringList;
    }

    /**
     * 返回数据
     *
     * @param searchResponse
     * @param keyword
     * @return
     */
    private List<String> parseResultData(SearchResponse<SuggestIndex> searchResponse, String keyword) {
        //  获取对应的补全集合!
        List<Suggestion<SuggestIndex>> keywordSuggest = searchResponse.suggest().get(keyword);
        if (!CollectionUtils.isEmpty(keywordSuggest)){
            //  获取到提词对象
            Suggestion<SuggestIndex> suggestIndexSuggestion = keywordSuggest.get(0);
            //  判断提词对象是否为空
            if (null != suggestIndexSuggestion){
                //  获取提词集合数据
                List<String> list = suggestIndexSuggestion.completion().options().stream().map(option -> {
                    return option.source().getTitle();
                }).collect(Collectors.toList());
                return list;
            }
        }
        //  默认返回空
        return new ArrayList<>();
    }

    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        //  每个map 中要存储两个key ；baseCategory3=三级分类对象 list=专辑集合;
        //  需要根据一级分类Id找到对应三级分类对象集合
        Result<List<BaseCategory3>> listResult = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(listResult, "三级分类集合不存在！");
        List<BaseCategory3> baseCategory3List = listResult.getData();
        Assert.notNull(baseCategory3List, "三级分类数据为空！");
        //  将这个集合 baseCategory3List 专辑map key=category3Id, value=baseCategory3;
        //        Map<Long, BaseCategory3> baseCategory3Map = baseCategory3List.stream().collect(Collectors.toMap(baseCategory3 -> {
        //                    return baseCategory3.getId();
        //                }, baseCategory3 -> {
        //                    return baseCategory3;
        //                }
        //        ));
        Map<Long, BaseCategory3> baseCategory3Map = baseCategory3List.stream().collect(Collectors.toMap(BaseCategory3::getId, basecategory3 -> basecategory3));

        //  根据这条dsl 语句 ，将数据从es中获取到！
        /*
        GET /albuminfo/_search
        {
          "query": {
            "terms": {
              "category3Id": [
                "1001",
                "1002",
                "1003",
                "1004",
                "1005",
                "1006",
                "1007"
              ]
            }
          },
          "aggs": {
            "category3Id_agg": {
              "terms": {
                "field": "category3Id",
                "size": 10
              },
              "aggs": {
                "top_six_hits": {
                  "top_hits": {
                    "size": 6,
                    "sort": [
                      {
                        "playStatNum": {
                          "order": "desc"
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        }

         */
        //  从这个集合 baseCategory3List 中获取三级分类Id集合
        List<Long> category3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //  将 List<Long> 转换为 List<FieldValue>
        List<FieldValue> valueList = category3IdList.stream().map(category3Id -> {
            return FieldValue.of(category3Id);
        }).collect(Collectors.toList());
        //  执行dsl语句;
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                            .query(q -> q.terms(t -> t.field("category3Id").terms(ts -> ts.value(valueList))))
                            .aggregations("category3Id_agg", a -> a.terms(t -> t.field("category3Id"))
                                    .aggregations("top_six_hits", a1 -> a1.topHits(t -> t.size(6).sort(s1 -> s1.field(f -> f.field("playStatNum").order(SortOrder.Desc)))))
                            )
                    ,
                    AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取检索结果集：
        Aggregate category3IdAgg = searchResponse.aggregations().get("category3Id_agg");
        //  map.put("baseCategory3",三级分类对象); map.put("list",专辑集合);
        List<Map<String, Object>> mapList = category3IdAgg.lterms().buckets().array().stream().map(bucket -> {
            //  声明一个map 集合;
            Map<String, Object> map = new HashMap<>();
            //  获取到三级分类Id
            long category3Id = bucket.key();
            //  获取到专辑集合
            List<AlbumInfoIndex> albumInfoIndexList = bucket.aggregations().get("top_six_hits").topHits().hits().hits().stream().map(hit -> {
                //  获取source 对象;
                String dataStr = hit.source().toString();
                //  将每个字符串对象转换为 AlbumInfoIndex 对象
                return JSON.parseObject(dataStr, AlbumInfoIndex.class);
            }).collect(Collectors.toList());
            //  存储三级分类对象
            map.put("baseCategory3", baseCategory3Map.get(category3Id));
            //  存储专辑集合
            map.put("list", albumInfoIndexList);
            //  返回map 对象
            return map;
        }).collect(Collectors.toList());
        //  返回集合对象
        return mapList;
    }

    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
        /*
          1. 获取数据.
            a. 根据用户输入的检索条件动态生成dsl 语句.
                如何判断用户到底是通过什么条件进行检索的?
                    判断这个对象的属性是否为null; 如果不为空，则用户就是按照这个条件进行检索的！
            b. 根据dsl 语句 在es索引库中执行查询.
            c. 从查询结果集中获取想要的字段信息.
         */
        //  判断这个对象的属性是否为null; 如果不为空，则用户就是按照这个条件进行检索的！
        //  1.  先获取到SearchRequest 对象; 包含的就是dsl 语句！
        SearchRequest searchRequest = this.queryBuildDsl(albumIndexQuery);
        //  2.  调用search方法查询数据
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  3.  将查询结果集进行转换
        AlbumSearchResponseVo albumSearchResponseVo = this.parseResultData(searchResponse);
        //  第三步：这个对象 albumSearchResponseVo的list , total 已经赋值。
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        //  totalPages  10 3 4 | 9 3 3
        //        Long totalPages = albumSearchResponseVo.getTotal() % albumIndexQuery.getPageSize() == 0 ?
        //                albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() :
        //                albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() + 1;
        Long totalPages = (albumSearchResponseVo.getTotal() + albumIndexQuery.getPageSize() - 1) / albumIndexQuery.getPageSize();
        //  赋值总页数
        albumSearchResponseVo.setTotalPages(totalPages);
        //  返回数据
        return albumSearchResponseVo;
    }

    /**
     * 检索数据进行转换
     * 给 list , total 已经赋值
     *
     * @param searchResponse
     * @return
     */
    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
         /*
        private List<AlbumInfoIndexVo> list = new ArrayList<>();
        private Long total;//总记录数
        private Integer pageSize;//每页显示的内容
        private Integer pageNo;//当前页面
        private Long totalPages;
         */
        //  获取结果集
        List<AlbumInfoIndexVo> list = searchResponse.hits().hits().stream().map(hit -> {
            //  获取数据
            AlbumInfoIndex albumInfoIndex = hit.source();
            //  创建对象 AlbumInfoIndexVo
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            //  属性拷贝
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //  判断用户是否通过关键词查询，可能有高亮字段
            if (null != hit.highlight().get("albumTitle")) {
                //  获取了高亮字段
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            //  返回数据
            return albumInfoIndexVo;
        }).collect(Collectors.toList());

        //  创建返回对象
        AlbumSearchResponseVo searchResponseVo = new AlbumSearchResponseVo();
        //  赋值专辑集合
        searchResponseVo.setList(list);
        searchResponseVo.setTotal(searchResponse.hits().total().value());
        //  返回封装好的数据对象
        return searchResponseVo;
    }

    /**
     * 动态构建dsl估计
     *
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest queryBuildDsl(AlbumIndexQuery albumIndexQuery) {
        //  创建searchRequest对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo");
        //  判断用户是通过关键词检索.
        String keyword = albumIndexQuery.getKeyword();
        if (!StringUtils.isEmpty(keyword)) {
            // query -- bool -- should
            searchRequestBuilder.query(q -> q.bool(b -> b.should(s -> s.match(m -> m.field("albumTitle").query(keyword)))
                            .should(s -> s.match(m -> m.field("albumIntro").query(keyword)))
                            .should(s -> s.match(m -> m.field("announcerName").query(keyword)))
                    )
            );
            //  设置高亮
            searchRequestBuilder.highlight(h -> h.fields("albumTitle", f -> f.preTags("<span style=color:#f86442>").postTags("</span>")));
        }
        //  判断分类Id 是否为空
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
            //  根据一级分类Id 过滤
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())))));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
            //  根据一级分类Id 过滤
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())))));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
            //  根据一级分类Id 过滤
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())))));
        }
        //  判断用户是否根据属性，属性值进行检索 属性Id:属性值Id
        List<String> attributeList = albumIndexQuery.getAttributeList();
        //  判断这个集合不为空
        if (!CollectionUtils.isEmpty(attributeList)) {
            //  循环遍历这个集合.
            for (String attribute : attributeList) {
                //  attribute 格式：属性Id:属性值Id
                String[] split = attribute.split(":");
                //  判断
                if (null != split && split.length == 2) {
                    //  query bool filter nested pat query bool filter term
                    searchRequestBuilder.query(q -> q.bool(b -> b.filter(
                            f -> f.nested(n -> n.path("attributeValueIndexList")
                                    .query(qy -> qy.bool(bl -> bl.filter(f1 -> f1.term(
                                                                    t1 -> t1.field("attributeValueIndexList.attributeId").value(split[0])
                                                            )
                                                    )
                                                    .filter(f2 -> f2.term(t2 -> t2.field("attributeValueIndexList.valueId").value(split[1])))
                                    )))
                    )));
                }
            }
        }
        //  排序： 排序（综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序）
        String order = albumIndexQuery.getOrder();
        //  判断
        if (!StringUtils.isEmpty(order)) {
            //  对order 进行一次分割
            String[] split = order.split(":");
            if (null != split && split.length == 2) {
                //  声明一个字段，来接收排序字段
                String field = "";
                switch (split[0]) {
                    case "1":
                        field = "hotScore";
                        break;
                    case "2":
                        field = "playStatNum";
                        break;
                    case "3":
                        field = "createTime";
                        break;
                }
                String finalField = field;
                searchRequestBuilder.sort(s -> s.field(f -> f.field(finalField).order("asc".equals(split[1]) ? SortOrder.Asc : SortOrder.Desc)));
            }
        }
        //  分页；
        int from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchRequestBuilder.from(from);
        searchRequestBuilder.size(albumIndexQuery.getPageSize());
        //  获取到searchRequest 对象.
        SearchRequest searchRequest = searchRequestBuilder.build();
        System.out.println("dsl:\t searchRequest " + searchRequest.toString());
        //  返回对象
        return searchRequest;
    }

    @Override
    public void lowerAlbum(Long albumId) {
        //  调用方法
        this.albumInfoIndexRepository.deleteById(albumId);
    }

    @Override
    public void upperAlbum(Long albumId) {
        //  上架的本质：给AlbumInfoIndex 赋值.
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //  要对获取数据这个过程进行优化！由单线程变多线程！
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //  赋值：
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            Assert.notNull(albumInfoResult, "获取专辑信息结果集失败！");
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo, "获取专辑信息失败！");
            //  属性拷贝：
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            //  返回数据
            return albumInfo;
        }, threadPoolExecutor).exceptionally(ex -> {
            log.error("获取专辑信息失败！", ex);
            return null;
        });
        //  获取分类数据.
        CompletableFuture<Void> voidCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  分类数据：
            Result<BaseCategoryView> baseCategoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            Assert.notNull(baseCategoryViewResult, "获取分类数据结果集失败！");
            BaseCategoryView baseCategoryView = baseCategoryViewResult.getData();
            Assert.notNull(baseCategoryView, "获取分类数据失败！");
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
            albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
        }, threadPoolExecutor);

        //  获取属性与属性值
        CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            Result<List<AlbumAttributeValue>> listResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Assert.notNull(listResult, "获取专辑属性值结果集失败！");
            List<AlbumAttributeValue> albumAttributeValueList = listResult.getData();
            Assert.notNull(albumAttributeValueList, "获取专辑属性值失败！");
            //  参数是谁? 集合对应的泛型就是参数.
            List<AttributeValueIndex> valueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                //  声明一个对象
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                //  返回数据
                return attributeValueIndex;
            }).collect(Collectors.toList());
            albumInfoIndex.setAttributeValueIndexList(valueIndexList);
        }, threadPoolExecutor);

        //  远程调用获取用户信息.
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  获取用户信息.
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "获取用户信息结果集失败！");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "获取用户信息失败！");
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);

        //  统计数据：
        albumInfoIndex.setSubscribeStatNum(new Random().nextInt(1000000));
        albumInfoIndex.setCommentStatNum(new Random().nextInt(10000));
        albumInfoIndex.setPlayStatNum(new Random().nextInt(100000000));
        albumInfoIndex.setBuyStatNum(new Random().nextInt(1000000));

        //  多任务组合：
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                voidCompletableFuture,
                attrCompletableFuture,
                userCompletableFuture
        ).join();


        //  albumInfoIndex 保存到es！
        albumInfoIndexRepository.save(albumInfoIndex);

        //  向提出库中添加数据. SuggestIndex 保存的专辑标题！
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        //  生成一个String 类型的数组 并初始化
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        //  保存专辑标题
        suggestIndexRepository.save(suggestIndex);

        //  简介
        SuggestIndex introSuggestIndex = new SuggestIndex();
        introSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        introSuggestIndex.setTitle(albumInfoIndex.getAlbumIntro());
        //  生成一个String 类型的数组 并初始化
        introSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        introSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        introSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        //  保存专辑简介
        suggestIndexRepository.save(introSuggestIndex);

        //  获取到布隆过滤器
        RBloomFilter<Object> bloomFilter = this.redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        //  将专辑的Id 添加到布隆过滤器中
        bloomFilter.add(albumId);
    }
}
